package com.xbongbong.paas.business.rule;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.pojo.BusinessRulesPoJo;
import com.xbongbong.paas.pojo.dto.ActiveRuleDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.businessrule.pojo.dto.ActiveRuleByUpdateBatchDTO;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.dictionary.pojo.DictionaryPojo;
import com.xbongbong.pro.dictionary.pojo.dto.DictionaryListDTO;
import com.xbongbong.pro.dictionary.pojo.vo.DictionaryVO;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.form.pojo.vo.FormBusinessRuleVO;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.dictionary.ContractStatusEnum;
import com.xbongbong.saas.enums.dictionary.DictionaryEnum;
import com.xbongbong.saas.model.DataDictionaryModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;


/**
 * @author: wufeng
 * @date: 2018/12/28 16:42
 * @desrcption: 表单数据生效规则
 */
@Component
public class FormDataActiveRuleByUpdateBatchHelp {

    private static final Logger LOG = LoggerFactory.getLogger(FormDataActiveRuleByUpdateBatchHelp.class);

    @Resource
    @Lazy
    private FormDataActiveRuleHelp formDataActiveRuleHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private DataDictionaryModel dataDictionaryModel;
    @Resource
    private BusinessRuleUserPermissionHelp businessRuleUserPermissionHelp;
    @Resource
    private BusinessRuleInfoService businessRuleInfoService;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Async(value = "activeRuleThreadPool")
    public void activeRuleByUpdateBatch(ActiveRuleByUpdateBatchDTO activeRuleByUpdateBatchDTO) throws XbbException{
        try {
            List<Long> dataIdList = activeRuleByUpdateBatchDTO.getFormDataIdList();
            if (CollectionsUtil.isEmpty(dataIdList)) {
                return;
            }
            String corpid = activeRuleByUpdateBatchDTO.getCorpid();
            if (businessRuleUserPermissionHelp.validateUsePermission(corpid)) {
                // 非旗舰版直接返回
                LOG.error("not have businessRule permission");
                return;
            }
            FormBusinessRuleVO businessRuleVO = businessRuleInfoService.get(corpid, activeRuleByUpdateBatchDTO.getFormId(), activeRuleByUpdateBatchDTO.getBusinessType(), activeRuleByUpdateBatchDTO.getSaasMark(), 0);
            List<BusinessRulesPoJo> businessRuleList = businessRuleVO.getBusinessRule();
            if (CollectionsUtil.isEmpty(businessRuleList)) {
                return;
            }
            if (Objects.isNull(businessRuleVO.getExcess()) || businessRuleVO.getExcess() > 0) {
                return;
            }
            if (businessRuleVO.getFormulaLimit()) {
                return;
            }
            List<PaasFormDataEntityExt> oldDataList = activeRuleByUpdateBatchDTO.getOldDataList();
            Map<Long, PaasFormDataEntityExt> oldDataMap = new HashMap<>(oldDataList.size());
            oldDataList.forEach(item->oldDataMap.put(item.getId(), item));
            //解析查询条件
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery("formId", activeRuleByUpdateBatchDTO.getFormId()));
            boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, dataIdList));
            boolQueryBuilder.filter(termQuery("del", 0));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            // 排序
            sourceBuilder.sort(new FieldSortBuilder(FieldTypeEnum.UPDATETIME.getAlias()).order(SortOrder.DESC));
            sourceBuilder.query(boolQueryBuilder);
            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, activeRuleByUpdateBatchDTO.getBusinessType(), activeRuleByUpdateBatchDTO.getSaasMark());
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            List<PaasFormDataEntityExt> list = paasEsModel.list(sourceBuilder, indexTypeEnum, new ArrayList<>(), 1, dataIdList.size());
            DictionaryPojo newStatusEntity = null;
            Boolean updateContractStatus = false;
            if (Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), activeRuleByUpdateBatchDTO.getBusinessType())
                    && ContractEnum.STATUS.getAttr().equals(activeRuleByUpdateBatchDTO.getAttr())) {
                DictionaryListDTO dictionaryListDTO = new DictionaryListDTO();
                BeanUtil.copyProperties(activeRuleByUpdateBatchDTO, dictionaryListDTO);
                dictionaryListDTO.setType(DictionaryEnum.CONTRACT_STATUS.getType());
                DictionaryVO dictionaryVO = dataDictionaryModel.list(dictionaryListDTO);
                if (Objects.isNull(dictionaryVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                List<DictionaryPojo> dictionaryList = dictionaryVO.getList();
                Map<String, DictionaryPojo> dictionaryMap = new HashMap<>(dictionaryList.size());

                for (DictionaryPojo item : dictionaryList) {
                    if (item.getEnable() == 1) {
                        dictionaryMap.put(item.getValue(), item);
                        if (activeRuleByUpdateBatchDTO.getValue().equals(item.getValue())) {
                            newStatusEntity = item;
                        }
                    }
                }
                if (newStatusEntity == null || !newStatusEntity.getEnable().equals(1)) {
                    updateContractStatus = true;
                }
            }
            Set<Long> parentIdList = new HashSet<>();
            Iterator<PaasFormDataEntityExt> iterator = list.iterator();
            while (iterator.hasNext()) {
                PaasFormDataEntityExt paasFormDataEntityExt = iterator.next();
                JSONObject data = paasFormDataEntityExt.getData();
                parentIdList.add(paasFormDataEntityExt.getDataId());
                if (Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), activeRuleByUpdateBatchDTO.getBusinessType())
                        && ContractEnum.STATUS.getAttr().equals(activeRuleByUpdateBatchDTO.getAttr())) {
                    if (updateContractStatus) {
                        data.put(ContractEnum.STATUS.getAttr(), 0);
                        data.put(ContractEnum.IF_STATISTIC.getAttr(), 0);
                    } else {
                        Integer ifStatistic = Objects.equals(newStatusEntity.getValue(), ContractStatusEnum.TERMINATION.getCode()) ? 0 : 1;
                        data.put(ContractEnum.STATUS.getAttr(), activeRuleByUpdateBatchDTO.getValue());
                        data.put(ContractEnum.IF_STATISTIC.getAttr(), ifStatistic);
                    }
                } else {
                    activeRuleByUpdateBatchDTO.getFieldEditedList().forEach(item->{

                        if (Objects.equals(item.getAttr(), FieldTypeEnum.DEPARTMENTID.getAlias())) {
                            if (item.getValue() instanceof Map || item.getValue() instanceof ReturnUserAndDepartmentPojo) {
                                JSONObject linkData = JSON.parseObject(JSON.toJSONString(item.getValue()));
                                if (Objects.nonNull(linkData)) {
                                    paasFormDataEntityExt.setDepartmentId(linkData.getLong(StringConstant.SAAS_LINK_BUSINESS_ID));
                                }
                            } else if (item.getValue() instanceof Long) {
                                paasFormDataEntityExt.setDepartmentId(Long.valueOf(JSON.toJSONString(item.getValue())));
                            }
                        } else {
                            data.put(item.getAttr(), item.getValue());
                        }
                    });
                }
            }
            Long formId = activeRuleByUpdateBatchDTO.getFormId();
            Integer businessType = activeRuleByUpdateBatchDTO.getBusinessType();
            // 获取子表单数据
            Map<Long, JSONObject> formDataMap = paasFormSubDataModel.getSubDataMap(corpid, activeRuleByUpdateBatchDTO.getSaasMark(), businessType, formId, parentIdList, 1, PaasConstant.SUB_DATA_PAGE_NUM, DelEnum.NORMAL.getDel());

            PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, formId, businessType);
            List<FieldAttrEntity> explainList = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            for (PaasFormDataEntityExt paasFormDataEntityExt: list) {
                JSONObject subForm = formDataMap.get(paasFormDataEntityExt.getDataId()) == null ? new JSONObject() : formDataMap.get(paasFormDataEntityExt.getDataId());
                paasFormDataEntityExt.setSubFormData(subForm);
                PaasFormDataEntityExt oldData = oldDataMap.get(paasFormDataEntityExt.getDataId());
                paasFormSubDataModel.transferSubForm(oldData, indexTypeEnum);
                ActiveRuleDTO activeRuleDTO = new ActiveRuleDTO(businessRuleList, paasFormDataEntityExt,  oldData, explainList, paasFormDataEntityExt.getDataId(),
                        activeRuleByUpdateBatchDTO.getBusinessType(), activeRuleByUpdateBatchDTO.getSaasMark(), activeRuleByUpdateBatchDTO.getCorpid(),activeRuleByUpdateBatchDTO.getLoginUser(), 1, activeRuleByUpdateBatchDTO.getPlatform(),
                        activeRuleByUpdateBatchDTO.getHttpHeader(), activeRuleByUpdateBatchDTO.getBrowserInfo(), activeRuleByUpdateBatchDTO.getIp(), activeRuleByUpdateBatchDTO.getLocale(), 0);
                formDataActiveRuleHelp.activeRuleBatch(activeRuleDTO);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("FormDataActiveRuleByUpdateBatchHelp.validateDataByInactiveRule 生效规则校验失败：", e);
        }
    }
}
